package org.fhm.zdte.common.util;


import org.fhm.substrate.annotation.Component;

import java.util.*;
import java.util.concurrent.ScheduledFuture;
import java.util.function.Supplier;

/**
 * Common utils
 *
 * @author 谭波
 * @since 2023/10/14
 */
@Component
public class CommonUtil {

    private final Random random = new Random();

    /**
     * Obtain new identification.
     * It is a six-digit number of random.
     *
     * @param identifications Old identification collection.
     * @return new identification.
     */
    public String getIdentification(Set<String> identifications) {
        if (Objects.isNull(identifications))
            return "00000";
        String result;
        do {
            result = String.valueOf(random.nextInt(90000) + 10000);
        } while (!identifications.isEmpty() && identifications.contains(result));
        return result;
    }

    /**
     * Obtain message number string.
     * It is a 32-digit uuid string.
     *
     * @return uuid string.
     */
    public String getMessageNumber() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * Currently obtain timestamp.
     *
     * @return Timestamp.
     */
    public long getCurTimeMillisSecond() {
        return System.currentTimeMillis();
    }

    /**
     * Cancel a specified task.
     *
     * @param task task.
     * @return <b>true</b> means cancel successful, <b>false</b> means cancel failed.
     */
    public boolean cancelTask(ScheduledFuture<?> task) {
        if (Objects.nonNull(task) && !task.isCancelled()) {
            boolean flag = false;
            while (!task.isCancelled()) {
                flag = task.cancel(true);
            }
            return flag;
        }
        return false;
    }

    /**
     * Obtain an object packaged by Thread-Local.
     *
     * @param tl        Thread-Local
     * @param createObj Provide how to create a specified object.
     * @param <T>       The type object of a specified object.
     * @return Specified object.
     */
    public <T> T obtainObjOfThreadLocal(ThreadLocal<T> tl, Supplier<T> createObj) {
        T t;
        if (Objects.isNull((t = tl.get()))) {
            synchronized (this) {
                if (Objects.isNull((t = tl.get()))) {
                    t = createObj.get();
                    tl.set(t);
                }
            }
        }
        return t;
    }

    /**
     * {@link List <Byte>} to byte array.
     *
     * @param listByte {@link List<Byte>}.
     * @return byte array.
     */
    public byte[] listByte2byteArray(List<Byte> listByte) {
        int size = listByte.size();
        byte[] bytes = new byte[size];
        for (int i = 0; i < size; i++)
            bytes[i] = listByte.get(i);
        return bytes;
    }

}
